aboutsummaryrefslogtreecommitdiff
path: root/src/app/(main)/websites/[websiteId]/(reports)/utm
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-01-24 13:09:50 +0000
committerFuwn <[email protected]>2026-01-24 13:09:50 +0000
commit396acf3bbbe00a192cb0ea0a9ccf91b1d8d2850b (patch)
treeb9df4ca6a70db45cfffbae6fdd7252e20fb8e93c /src/app/(main)/websites/[websiteId]/(reports)/utm
downloadumami-main.tar.xz
umami-main.zip
Initial commitHEADmain
Created from https://vercel.com/new
Diffstat (limited to 'src/app/(main)/websites/[websiteId]/(reports)/utm')
-rw-r--r--src/app/(main)/websites/[websiteId]/(reports)/utm/UTM.tsx71
-rw-r--r--src/app/(main)/websites/[websiteId]/(reports)/utm/UTMPage.tsx18
-rw-r--r--src/app/(main)/websites/[websiteId]/(reports)/utm/page.tsx12
3 files changed, 101 insertions, 0 deletions
diff --git a/src/app/(main)/websites/[websiteId]/(reports)/utm/UTM.tsx b/src/app/(main)/websites/[websiteId]/(reports)/utm/UTM.tsx
new file mode 100644
index 0000000..1399174
--- /dev/null
+++ b/src/app/(main)/websites/[websiteId]/(reports)/utm/UTM.tsx
@@ -0,0 +1,71 @@
+import { Column, Grid, Heading, Text } from '@umami/react-zen';
+import { PieChart } from '@/components/charts/PieChart';
+import { LoadingPanel } from '@/components/common/LoadingPanel';
+import { Panel } from '@/components/common/Panel';
+import { useMessages, useResultQuery } from '@/components/hooks';
+import { ListTable } from '@/components/metrics/ListTable';
+import { CHART_COLORS, UTM_PARAMS } from '@/lib/constants';
+
+export interface UTMProps {
+ websiteId: string;
+ startDate: Date;
+ endDate: Date;
+}
+
+export function UTM({ websiteId, startDate, endDate }: UTMProps) {
+ const { formatMessage, labels } = useMessages();
+ const { data, error, isLoading } = useResultQuery<any>('utm', {
+ websiteId,
+ startDate,
+ endDate,
+ });
+
+ return (
+ <LoadingPanel data={data} isLoading={isLoading} error={error} minHeight="300px">
+ {data && (
+ <Column gap>
+ {UTM_PARAMS.map(param => {
+ const items = data?.[param];
+
+ const chartData = {
+ labels: items.map(({ utm }) => utm),
+ datasets: [
+ {
+ data: items.map(({ views }) => views),
+ backgroundColor: CHART_COLORS,
+ borderWidth: 0,
+ },
+ ],
+ };
+ const total = items.reduce((sum, { views }) => {
+ return +sum + +views;
+ }, 0);
+
+ return (
+ <Panel key={param}>
+ <Grid columns={{ xs: '1fr', md: '1fr 1fr' }} gap="6">
+ <Column>
+ <Heading>
+ <Text transform="capitalize">{param.replace(/^utm_/, '')}</Text>
+ </Heading>
+ <ListTable
+ metric={formatMessage(labels.views)}
+ data={items.map(({ utm, views }) => ({
+ label: utm,
+ count: views,
+ percent: (views / total) * 100,
+ }))}
+ />
+ </Column>
+ <Column>
+ <PieChart type="doughnut" chartData={chartData} />
+ </Column>
+ </Grid>
+ </Panel>
+ );
+ })}
+ </Column>
+ )}
+ </LoadingPanel>
+ );
+}
diff --git a/src/app/(main)/websites/[websiteId]/(reports)/utm/UTMPage.tsx b/src/app/(main)/websites/[websiteId]/(reports)/utm/UTMPage.tsx
new file mode 100644
index 0000000..0d2a732
--- /dev/null
+++ b/src/app/(main)/websites/[websiteId]/(reports)/utm/UTMPage.tsx
@@ -0,0 +1,18 @@
+'use client';
+import { Column } from '@umami/react-zen';
+import { WebsiteControls } from '@/app/(main)/websites/[websiteId]/WebsiteControls';
+import { useDateRange } from '@/components/hooks';
+import { UTM } from './UTM';
+
+export function UTMPage({ websiteId }: { websiteId: string }) {
+ const {
+ dateRange: { startDate, endDate },
+ } = useDateRange();
+
+ return (
+ <Column gap>
+ <WebsiteControls websiteId={websiteId} />
+ <UTM websiteId={websiteId} startDate={startDate} endDate={endDate} />
+ </Column>
+ );
+}
diff --git a/src/app/(main)/websites/[websiteId]/(reports)/utm/page.tsx b/src/app/(main)/websites/[websiteId]/(reports)/utm/page.tsx
new file mode 100644
index 0000000..8b8fd6a
--- /dev/null
+++ b/src/app/(main)/websites/[websiteId]/(reports)/utm/page.tsx
@@ -0,0 +1,12 @@
+import type { Metadata } from 'next';
+import { UTMPage } from './UTMPage';
+
+export default async function ({ params }: { params: Promise<{ websiteId: string }> }) {
+ const { websiteId } = await params;
+
+ return <UTMPage websiteId={websiteId} />;
+}
+
+export const metadata: Metadata = {
+ title: 'UTM Parameters',
+};